# -*- coding:utf-8 -*- #

#引入上层目录模块方法
import sys
sys.path.append("..")

from logger.logger import getlogger
from conf import configure

class CmdLoader(object):
    """
    load config and format config to python readable
    monitorcfg = (
            ('probe.core.network.LongConnection', ('localhost', 2000)),
            (
                'cpu_state',#cmd 
                'probe.monitorprobes.system.cpu_state',#function
                (1, (5, 8, 10, 13)),#(cycle period, #(alarm level1, alarm level2, .)
                1,
                {'InfoData': 70, 'WarningData': 40}
                ), #extract param, can be any componet of type.

            ),
            )
    will format to:
    configs['monitorcfg'] = {'cpu_state': {'fun':
    probe.monitorprobes.system.cpu_state, 'rate': (1, (5, 8, 10, 13)),
    'param': {'InfoData': 70, 'WarningData': 40}, 'id': 1, 'inet':
    LongConnection(('localhost', 2000))}

    """

    #_shared = {}

    #def __init__(self, cmds=''):
        #print type(cmds)
        #print cmds
        #self.__dict__ = self._shared
        #if not self._shared:
            #self.load(cmds)
    def __init__(self):
        
        self.configs = {}
        self.min_param = 4
        self.max_param = 5
    
    def load(self, cmds):
        
        '''将配置信息载入到内存中
        @param cmds 字典对象
        '''

        for k, v in cmds.iteritems():
            #k是monitorcfg alarmcfg
            #v是对应他们的值
            try:
                self.configs[k] = self._resolve(v)
            except AssertionError:
                getlogger(configure.logger_path).error('config %s:%s error' % (k, str(v)))

    def reload_config(self, cmds):
        self.load(cmds)

    
    def _resolve(self, data):
        # data的数据为 monitorcfg 后面的值,monitorcfg是一个例子，还有其他的
        if not len(data):
            return

        config = {}
        # data[0] = ('probe.core.network.ShortConnection', ('162.16.10.253', 2000))
        assert len(data[0]) == 2
        try:
            conn = None
            for d in data:
                if len(d) == 2:
                    #得到连接配置
                    # d = ('probe.core.network.ShortConnection', ('162.16.10.253', 2000))
                    # conn =  <core.network.ShortConnection object at 0xb7bdb02c>
                    # type(conn) = <class 'core.network.ShortConnection'>
                    # d[1] =  ('162.16.10.253', 2000)
                    conn = self._load_func(d[0])(d[1])
                else:
                    assert len(d) >= self.min_param and len(d) <= self.max_param
                    param = None
                    if len(d) == self.max_param:
                        # param = {'WarningData': 10}
                        param = d[4]
                        
                        try:
                            assert type(param) is dict
                        except AssertionError:
                            getlogger(configure.logger_path).error("type of param:%s is not dict" % param)
                            #raise TypeError

                    try:
                        assert len(d[2]) >= 1
                        assert type(d[3]) is dict and len(d[3]) == 1
                    except AssertionError:
                        getlogger(configure.logger_path).error(('configure file is not'
                                'correct(format error:should be tuple or'
                                ' dict): %s' % (str(data))))

                    '''
                    d[0]=== disk_space
                    d[1]=== monitorprobes.disk_space.get_disk_space
                    d[2]=== (1, (30, 60, 120, 180))
                    d[3]=== {'id': 21}
                    '''
                    config[d[0]] = {'fun': self._load_func(d[1]),
                            'rate': d[2], 'id': d[3]['id'], 'param': param,
                                'inet': conn}

        except IndexError:
            getlogger(configure.logger_path).error('parameters %s format is not correct')
            #raise IndexError('parameters %s format is not correct')
        except AssertionError:
            getlogger(configure.logger_path).error('network conf  param:%s is not correct')
            #raise AssertionError

        '''
        config是一个字典，格式如下
        {'disk_space': 
        {'fun': <function get_disk_space at 0xb7b7a95c>, 
        'rate': (1, (30, 60, 120, 180)), 
        'inet': <core.network.ShortConnection object at 0xb7c8fb2c>, 
        'id': 21, 
        'param': {'WarningData': 10}}
        }
        '''
        return config

    def detail(self, key):
        '''
        返回对应key的内容
        '''
        return self.configs[key]

    def _load_func(self, cmd):
        '''
        加载配置文件中配置的文件模块
        cmd = core.network.ShortConnection  例子
        '''
        
        last_point = 0
        try:
            #得到最后一个.的位置
            last_point = cmd.rindex('.')
        except ValueError:
            getlogger(configure.logger_path).error('%s should be added with module name' % cmd)

            #raise ValueError('%s should be added with module name' % cmd)

        # 假设 cmd = probe.core.network.ShortConnection
        module = cmd[:last_point]         # 得到 probe.core.network
        func = cmd[last_point + 1:]        # 得到 ShortConnection
        exec "import %s" % module          #载入模块
        return eval("%s.%s" % (module, func))

    def get_config(self, config_name):
        return self.configs[config_name]
